#include <rclcpp/rclcpp.hpp>
#include <tf2_ros/buffer.hpp>
#include <tf2_ros/transform_listener.hpp>
using namespace std::chrono_literals;
class TFListenerCppNode : public rclcpp::Node
{
private:
	std::unique_ptr<tf2_ros::Buffer> buffer_;
	std::shared_ptr<tf2_ros::TransformListener> listener_;
	rclcpp::TimerBase::SharedPtr timer_;

public:
	TFListenerCppNode() : Node("tf_listener_cpp_node")
	{
		RCLCPP_INFO(this->get_logger(), "TFListenerCppNode创建");
		buffer_ = std::make_unique<tf2_ros::Buffer>(this->get_clock());
		listener_ = std::make_shared<tf2_ros::TransformListener>(*buffer_, this);
		timer_ = create_wall_timer(1s, std::bind(&TFListenerCppNode::on_timer, this));
	}

private:
	void on_timer()
	{
		/*
		lookupTransform(const std::string &target_frame,
		const std::string &source_frame,
		const tf2::TimePoint &time)
		*/
		try
		{

			// "camera"  target_frame 父坐标系
			// "laser"   source_frame
			// tf2::TimePointZero 这个表示最新的
			geometry_msgs::msg::TransformStamped ts = buffer_->lookupTransform("camera", "laser", tf2::TimePointZero);
			RCLCPP_INFO(this->get_logger(), "转换完成的坐标系信息");
			RCLCPP_INFO(this->get_logger(), "父坐标系%s 子坐标系%s,偏移量(%.2f,%.2f,%.2f)",
						ts.header.frame_id.c_str(), ts.child_frame_id.c_str(),
						ts.transform.translation.x,
						ts.transform.translation.y,
						ts.transform.translation.z);
		}

		catch (const tf2::LookupException &e)
		{
			RCLCPP_ERROR(this->get_logger(), "异常提示：%s", e.what());
		}
	}
};
int main(int argc, char **argv)
{
	rclcpp::init(argc, argv);
	rclcpp::spin(std::make_shared<TFListenerCppNode>());
	rclcpp::shutdown();
	return 0;
}
/*
ros2 run tf2_ros static_transform_publisher --frame-id base_link --child-frame-id laser --x 0.4 --z 0.2
ros2 run tf2_ros static_transform_publisher --frame-id base_link --child-frame-id camera --x -0.5 --z 0.4
ros2 run tf2_ros tf2_echo camera laser
buffer_是一个带时间戳的坐标系关系数据库​

它存储的是坐标系之间的变换关系（Transform），而不是直接的树结构

但基于这些关系，TF2 会在内部构建一个动态的坐标系树
主题通信机制​：

变换数据通过 /tf（动态变换）和 /tf_static（静态变换）主题传输

这是标准的 ROS 2 发布-订阅模式

​Buffer 作为存储​：

TransformListener订阅这些主题

接收到的变换数据存储在 Buffer中

Buffer 维护一个时间序列的变换数据库

*/
